﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;

namespace stackedMenuTest01_sl3
{

    // The delegate will encapsulate the clicked event of the menu
    public delegate void OptionClicked(String Option, EventArgs e); 

    public partial class StackedMenu : UserControl
    {
        // An event that clients can use to be notified whenever the process has been completed. 
        public event OptionClicked OptionClickedEvent;

        // Invoke the CalcPreuOnCompleted event; called when the process is complete 
        protected virtual void OnClicked(String option, EventArgs e)
        {
            if (OptionClickedEvent != null)
                OptionClickedEvent(option, e);
        }


        public StackedMenu()
        {
            InitializeComponent();
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            //Once loaded, the menu is drawn
            drawmenu();
        }


        private PathFigure figure;
        double StrokeThickness = 0.5;
        ObservableCollection<MenuItem> ocMenuItems;
        List<String> lsMenuItemNames ;
        double Block_Width = 350; //200;
        double Block_Height = 60; //30;
        int numberOfBlocks ;

        void drawmenu() {
            //Inicializar la colección de MenuItems en una funcion aparte (nombre, imagen, uc1, uc2, etc...)
            ocMenuItems = new ObservableCollection<MenuItem>();
            lsMenuItemNames = new List<string>() { "Print Badge", "Directions", "Purchase Raffle Tickets" };
            //lsMenuItemNames = new List<string>() { "Registration"};
            numberOfBlocks = lsMenuItemNames.Count;

            double InitialTop = 30;
            double InitialLeft = 30;
            double tmpTop = InitialTop;
            double tmpLeft = InitialLeft;
            double verticalSeparator = 2;
            int iniOffset = -10;
            int endOffset = 25;
            int BackScaleTo = 4;
            int BackScaleToHorizontal = 2;
            int BackScaleToVertical = 5;
            //Parameters for determining Final position (Expanded)
            int verticalExpandedOffset = 95;
            int verticalExpandedSeparator = -10;

            int BackLeftOffset = (int)Math.Round((Block_Width /1.2), 0);
            
            //starting from the bottom..
            double BackHeight = Block_Height / BackScaleToVertical;
            double BackStackedHeight = BackHeight * numberOfBlocks;
            double StackedHeight = Block_Height * (numberOfBlocks+1);
            var BackVerticalInitialPoint = StackedHeight - BackStackedHeight;

            //Temporal Parameters for determining Final position (Expanded)
            //int verticalExpandedOffset = 75;
            int acumulatedExpandedSeparator = 0;
            Random r = new Random();
            for (int i = 0; i < numberOfBlocks; i++)
            {
                //A random offset for the horizontal position...so we slide them a bit to the right or left so it seems like they have fallen down..
                double MenuOffset = (double)r.Next(iniOffset,endOffset);
                
                //Creation of the menu item  and adding the Front Points.
                MenuItem mi = new MenuItem() { 
                     TL = new Point(tmpLeft + MenuOffset, tmpTop),
                     TR = new Point(tmpLeft + MenuOffset + Block_Width, tmpTop),
                     BR = new Point(tmpLeft + MenuOffset + Block_Width, tmpTop + Block_Height),
                     BL = new Point(tmpLeft + MenuOffset, tmpTop + Block_Height),
                };

                //Adding the back points to the menu item .
                //int BackTopOffset = (int)Math.Round(BackVerticalInitialPoint + ((i+1) * BackHeight),0);
                double BackTopOffset = BackVerticalInitialPoint + ((i + 1) * BackHeight);
                mi.BTL = new Point(mi.TL.X + BackLeftOffset, BackTopOffset);
                mi.BTR = new Point(mi.BTL.X + (Block_Width / BackScaleToHorizontal), mi.BTL.Y);
                mi.BBR = new Point(mi.BTL.X + (Block_Width / BackScaleToHorizontal), mi.BTL.Y + BackHeight);
                mi.BBL = new Point(mi.BTL.X, mi.BTL.Y + BackHeight);

                //Now we add the Expanded position for the front points (back points stay in place).
                mi.E_BL = new Point(mi.BL.X, mi.BL.Y - (acumulatedExpandedSeparator + verticalExpandedOffset));
                mi.E_BR = new Point(mi.BR.X, mi.BR.Y - (acumulatedExpandedSeparator + verticalExpandedOffset));
                mi.E_TL = new Point(mi.TL.X, mi.TL.Y - (acumulatedExpandedSeparator + verticalExpandedOffset));
                mi.E_TR = new Point(mi.TR.X, mi.TR.Y - (acumulatedExpandedSeparator + verticalExpandedOffset));

                //By default they are collapsed
                mi.Collapsed = true;

                //We also give it a name.
                mi.name = lsMenuItemNames[i]; //i.ToString();  //

                //We add the Menu Item 
                ocMenuItems.Add(mi);

                tmpTop = tmpTop + (Block_Height + verticalSeparator); //Offset?
                acumulatedExpandedSeparator = acumulatedExpandedSeparator + verticalExpandedSeparator;
            }

            int imnuoption = 0;
            //Colors for the blocks sides.
            // Front side -  light gray  - #FFE4E3E5
            // Right side -  middle gray - #FFB7B7B8
            // Bottom side - darker gray - #FF878889
            SolidColorBrush BaseFrontColor = getColorFromHEXaString("#FFE4E3E5");
            SolidColorBrush BaseRightSideColor = getColorFromHEXaString("#FFB7B7B8");
            SolidColorBrush BaseBottomColor = getColorFromHEXaString("#FF878889");


            //We create the different paths for each Menu Item:  Front, Right, and bottom. There is also the Back but that is just for tests.
            //Here we also wire up the events too.
            foreach (var m in ocMenuItems)
            {
               String BasePrefix = "opt" + imnuoption.ToString();
               String prefix = BasePrefix + "Front";
               
               //Front Face
               Path p = CreatePath(m.TL, m.TR, m.BR, m.BL, BaseFrontColor, prefix);
               p.Name = "front_" + imnuoption.ToString();
               //p.MouseEnter += new MouseEventHandler(p_MouseEnter);
               //p.MouseLeave += new MouseEventHandler(p_MouseLeave);
               //p.MouseMove += new MouseEventHandler(p_MouseMove);
               //p.MouseLeftButtonDown += new MouseButtonEventHandler(p_MouseLeftButtonDown);
               this.menuCanvas.Children.Add(p);

               //Additionally, we have a Usercontrol that we "paste" and position over the Front Face - it is the "FrontMenuOption".
               m.fo = new FrontMenuOption();
               m.fo.optionName.Text = m.name; //"Option Nº" + imnuoption.ToString();
               m.fo.Width = Block_Width;
               m.fo.Height = Block_Height;
               m.fo.SetValue(Canvas.TopProperty, m.TL.Y);
               m.fo.SetValue(Canvas.LeftProperty, m.TL.X);
               m.fo.SetValue(NameProperty, BasePrefix + "FrontPlate" + imnuoption.ToString());
               //figure.SetValue(Control.NameProperty, prefix + "0");

               m.fo.MouseMove += new MouseEventHandler(p_MouseMove);
               m.fo.MouseLeftButtonDown += new MouseButtonEventHandler(p_MouseLeftButtonDown);
               this.menuCanvas.Children.Add(m.fo);
               
               //The Back Face (only for tests)
               //prefix = BasePrefix + "Back";
               //Path pR = CreatePath(m.BTL, m.BTR, m.BBR, m.BBL, new SolidColorBrush(Colors.Green), prefix);
               //this.menuCanvas.Children.Add(pR);

               //The Right Face
               prefix = BasePrefix + "Right";
               Path rpR = CreatePath(m.TR, m.BTR, m.BBR, m.BR, BaseRightSideColor, prefix);
               this.menuCanvas.Children.Add(rpR);

               //The Bottom Face
               prefix = BasePrefix + "Bottom";
               Path bpb = CreatePath(m.BL, m.BR, m.BBR, m.BBL, BaseBottomColor, prefix);
               this.menuCanvas.Children.Add(bpb);

               //And another one...
               imnuoption++;
            }
        }

        #region Interaction Methods
        bool animating = false;
        bool OptionCollapsed = true;  //This only allows us to change only one option. should we implement a collapsed boolean prop in the menuitem class - that will do.
        void p_MouseMove(object sender, MouseEventArgs e)
        {
            UserControl p = (UserControl)sender;
            string nom = p.Name;
            String option = nom.Substring(nom.Length - 1, 1);

            AnimateOptions(option);
        }
        void p_MouseLeave(object sender, MouseEventArgs e)
        {
            //AnimateOption();
        }
        void p_MouseEnter(object sender, MouseEventArgs e)
        {
            //AnimateOption();
        }
        void p_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            UserControl p = (UserControl)sender;
            string nom = p.Name;
            String option = nom.Substring(nom.Length - 1, 1);


            OnClicked(option, new EventArgs());

            ////Execute click action for the option - this is done on event capture..
            //switch (option)
            //{
            //    case "0":
            //        //Do something... child windows???
            //        break;
            //    case "1":
            //        break;
            //    case "2":
            //        break;
            //    default:
            //        break;
            //}
        }
        private void AnimateOptions(string option)
        {
            //option indicates the selected option.
            if (animating == false)
            {
                //If it is folded we make the unfold animation, if it is unfolded we unfold
                //animating = true;
                //int direction = 1;
                //if (OptionCollapsed)
                //    direction = -1;

                bool tmpCollapsed = true; //This is to indicate the AnimateTo function what should he do with the options, collapse or expand them...
                int iOption = Convert.ToInt32(option);
                //Decission if the options must be all collapsed...
                
                bool collapseAll = false;
                if (ocMenuItems[iOption].Collapsed == false) {
                    collapseAll = true;
                }
                //tmpCollapsed = !ocMenuItems[iOption].Collapsed; //Invertimos...
                //OptionCollapsed = !OptionCollapsed;
                LayoutRoot.Resources.Clear();

                //int i = 0;

                for (int i = ocMenuItems.Count-1; i >= 0 ; i--)
                {
                    var tmpOption = ocMenuItems[i];
                    if (i == iOption)
                    {
                        //We decide what to do here, collapse options (if they are expanded) or Expand them (if they are collapsed..)
                        if (collapseAll == false) //If the selected option is marked for collapse, we have to collapse all. Else, we Expand starting from the selected option.
                        {
                            tmpCollapsed = !tmpOption.Collapsed;
                        }
                        animateTo(i, true, tmpCollapsed);
                    }
                    else
                    { //Collapse all  == true...
                        animateTo(i, false, tmpCollapsed);
                    }

                    //Actualizamos el estado de Collapsed
                    tmpOption.Collapsed = tmpCollapsed;

                }
                //foreach (var tmpOption in ocMenuItems)
                //{
                //    if (i == iOption)
                //    {
                //        //We decide what to do here, collapse options (if they are expanded) or Expand them (if they are collapsed..)
                //        if (collapseAll == false) //If the selected option is marked for collapse, we have to collapse all. Else, we Expand starting from the selected option.
                //        {
                //            tmpCollapsed = !tmpOption.Collapsed;
                //        }
                //        animateTo(i, true, tmpCollapsed);
                //    }
                //    else { //Collapse all  == true...
                //        animateTo(i, false, tmpCollapsed);
                //    }
                    
                //    //Actualizamos el estado de Collapsed
                //    tmpOption.Collapsed = tmpCollapsed;

                //    i = i + 1;
                //}

                //animateTo(0, 90 * direction, false);
                //animateTo(1, 85 * direction, false);
                //animateTo(2, 80 * direction, false);
                //animateTo(3, 75 * direction, true);
            }
        }
        #endregion Interaction Methods

        #region Helper Methods
        private Path CreatePath(Point TL, Point TR, Point BR, Point BL, SolidColorBrush scb, String prefix)
        {
            PathFigure pf = new PathFigure();
            var geometry = new PathGeometry();
            figure = new PathFigure();
            figure.SetValue(Control.NameProperty, prefix + "0");

            figure.StartPoint = TL;
            AddPoint(figure, TR.X, TR.Y, prefix + "1");
            AddPoint(figure, BR.X, BR.Y, prefix + "2");
            AddPoint(figure, BL.X, BL.Y, prefix + "3");
            figure.IsClosed = true;
            geometry.Figures.Add(figure);

            Path p = new Path();
            p.Data = geometry;
            p.Stroke = new SolidColorBrush(Colors.Black); // scb; // new SolidColorBrush(Colors.Blue);
            p.StrokeThickness = StrokeThickness;
            //SolidColorBrush blueBrush = new SolidColorBrush();
            //blueBrush.Color = Colors.LightGray;
            p.Fill = scb;
            //p.Fill = new brush 
            p.Stretch = Stretch.None;

            return p;
        }
        private void AddPoint(PathFigure figure, double x, double y, string sName)
        {
            LineSegment segment = new LineSegment();
            segment.SetValue(Control.NameProperty, sName);
            //segment.Point = new Point(x + 0.5 * StrokeThickness, y + 0.5 * StrokeThickness);
            segment.Point = new Point(x, y);
            figure.Segments.Add(segment);
        }
        SolidColorBrush getColorFromHEXaString(string colorcode)
        {
            // Input like "#FF909cd0";
            SolidColorBrush brush = new SolidColorBrush();
            Color c = new Color();
            c.A = Convert.ToByte(colorcode.Substring(1, 2), 16);
            c.R = Convert.ToByte(colorcode.Substring(3, 2), 16);
            c.G = Convert.ToByte(colorcode.Substring(5, 2), 16);
            c.B = Convert.ToByte(colorcode.Substring(7, 2), 16);
            brush.Color = c;
            return brush;
        }
        #endregion Helper Methods


        #region old code
        //private PathGeometry CreateBlock(double iniX, double iniY, double Width, double Height) {
        //    PathFigure pf = new PathFigure();

        //    // in order to fit in our layout slot we need to reduce the size of the stroke
        //    //Height -= this.StrokeThickness;
        //    //Width -= this.StrokeThickness;

        //    //// needed to avoid a layout loop
        //    //if (lastWidth == width && lastHeight == height) return;
        //    //lastWidth = width;
        //    //lastHeight = height;

        //    var geometry = new PathGeometry();
        //    figure = new PathFigure();

        //    figure.StartPoint = new Point(iniX, iniY );
        //    AddPoint(figure, Width, iniY );
        //    AddPoint(figure, Width, Height);
        //    AddPoint(figure, iniX, Height);
        //    figure.IsClosed = true;
        //    geometry.Figures.Add(figure);

        //    //figure.StartPoint = new Point(0 + 0.5 * StrokeThickness, height + 0.5 * StrokeThickness);
        //    //AddPoint(width, height);
        //    //AddPoint(width / 2, 0);
        //    //AddPoint(0, height);
        //    //figure.IsClosed = true;
        //    //geometry.Figures.Add(figure);
        //    //this.Data = geometry;

        //    return geometry;
        //} 
        //private void animate_Click(object sender, RoutedEventArgs e)
        //{
        //    AnimateOption();
        //    return;
        //    //Implement with???
        //    //PointAnimation? http://msdn.microsoft.com/en-us/library/cc189069(VS.95).aspx
        //    //http://www.c-sharpcorner.com/UploadFile/dpatra/PointAnimationInSilverlight307172009141610PM/PointAnimationInSilverlight3.aspx
        //    //http://msdn.microsoft.com/en-us/library/system.windows.media.pathgeometry(VS.95).aspx
        //    //PathGeometry - http://msdn.microsoft.com/en-us/library/system.windows.media.pathgeometry(VS.95).aspx
        //    //PathFigureCollection - http://msdn.microsoft.com/en-us/library/system.windows.media.pathfigurecollection(VS.95).aspx
        //    //PathFigure - http://msdn.microsoft.com/en-us/library/system.windows.media.pathfigure(VS.95).aspx
        //    // Geometry is composed of one or more PathFigure(s). these are in a PathFigureCollection
        //    // PathGeometry - PathFigureCollection - PathFigure - 
        //    // StartPoint (of the PathFigure) and LineSegments...
        //    // LineSegments - http://msdn.microsoft.com/en-us/library/system.windows.media.linesegment(VS.95).aspx
        //    double offset = 100;
        //    int option = 0;
        //    int increment = (int)offset * 5;
        //    double step = offset / increment;

        //    // Create a duration of 2 seconds.
        //    Duration duration = new Duration(TimeSpan.FromSeconds(2));

        //    // Create two DoubleAnimations and set their properties.
        //    DoubleAnimation myDoubleAnimationTL = new DoubleAnimation();
        //    DoubleAnimation myDoubleAnimationTR = new DoubleAnimation();
        //    DoubleAnimation myDoubleAnimationBR = new DoubleAnimation();
        //    DoubleAnimation myDoubleAnimationBL = new DoubleAnimation();

        //    myDoubleAnimationTL.Duration = duration;
        //    myDoubleAnimationTR.Duration = duration;
        //    myDoubleAnimationBR.Duration = duration;
        //    myDoubleAnimationBL.Duration = duration;

        //    Storyboard sb = new Storyboard();
        //    sb.Duration = duration;

        //    //sb.Children.Add(myDoubleAnimationTL);
        //    //sb.Children.Add(myDoubleAnimationTR);
        //    //sb.Children.Add(myDoubleAnimationBR);
        //    //sb.Children.Add(myDoubleAnimationBL);

        //    //String Name = "opt" + "0" + "Front" + "1"; //"front_" + option.ToString(); 
        //    //Path target = (Path)this.menuCanvas.FindName(Name);
        //    //Storyboard.SetTarget(myDoubleAnimationTL, target);
        //    //Storyboard.SetTargetProperty(myDoubleAnimationTL, new PropertyPath("(Point)"));

        //    //http://visualstudiomagazine.com/articles/2008/09/29/animating-clipping-paths-in-silverlight-2.aspx


        //    ////////////////////////////////////////////////////////////////////////////
        //    /// JL: ESTO FUNCIONA BIEN :)
        //    ////////////////////////////////////////////////////////////////////////////
        //    //PointAnimation P1Anim = new PointAnimation();
        //    //String Name = "opt" + "0" + "Front" + "1";
        //    //LineSegment lsTarget = (LineSegment)this.menuCanvas.FindName(Name);
        //    //PropertyPath pp = new PropertyPath("(Point)");
        //    //Storyboard.SetTargetProperty(P1Anim, pp);
        //    //Storyboard.SetTarget(P1Anim, lsTarget);
        //    //P1Anim.To = new Point(10, -100);
        //    //sb.Children.Add(P1Anim);
        //    ////////////////////////////////////////////////////////////////////////////
        //    /// JL: ESTO FUNCIONA BIEN :)
        //    ////////////////////////////////////////////////////////////////////////////
        //    double VertTo = -70;

        //    //Rectangulo superior
        //    PointAnimation pa1TL = GenPointStartAnimation(0, "Front", VertTo);
        //    PointAnimation pa1TR = GenPointAnimation(0, 1, "Front", VertTo);
        //    PointAnimation pa1BR = GenPointAnimation(0, 2, "Front", VertTo);
        //    PointAnimation pa1BL = GenPointAnimation(0, 3, "Front", VertTo);
        //    //Rectangulo derecho
        //    PointAnimation pa2TL = GenPointStartAnimation(0, "Right", VertTo);
        //    PointAnimation pa2TR = GenPointAnimation(0, 3, "Right", VertTo);
        //    //Rectangulo inferior
        //    PointAnimation pa3TL = GenPointStartAnimation(0, "Bottom", VertTo);
        //    PointAnimation pa3TR = GenPointAnimation(0, 1, "Bottom", VertTo);

        //    //Generamos una lista para tratar las animaciones de punto de forma automatica
        //    List<PointAnimation> lpa = new List<PointAnimation>();
        //    lpa.Add(pa1TL);
        //    lpa.Add(pa1TR);
        //    lpa.Add(pa1BR);
        //    lpa.Add(pa1BL);
        //    lpa.Add(pa2TL);
        //    lpa.Add(pa2TR);
        //    lpa.Add(pa3TL);
        //    lpa.Add(pa3TR);

        //    //El easing que aplicaremos a todas las animaciones
        //    var easing = new BounceEase();
        //    easing.Bounces = 2;
        //    easing.EasingMode = EasingMode.EaseIn;
        //    var ElasticEase = new ElasticEase();
        //    ElasticEase.EasingMode = EasingMode.EaseOut;
        //    ElasticEase.Oscillations = 1;
        //    ElasticEase.Springiness = 1;

        //    //Aplicamos el easing y añadimos todas las animaciones al Storyboard
        //    foreach (var item in lpa)
        //    {
        //        //Asignamos la función de ease
        //        item.EasingFunction = ElasticEase; // easing;
        //        //Añadimos las animaciones...
        //        sb.Children.Add(item);
        //    }

        //    LayoutRoot.Resources.Clear();
        //    LayoutRoot.Resources.Add("animationofmenu", sb);
        //    sb.Begin();
        //}
        #endregion old code


        //private void animateTo(int option, double offset, bool selected ) 
        private void animateTo(int option, bool selected, bool collapsed ) 
        {
            //int option = 0;
            double duracion = 1.2;

            // Create a duration of 2 seconds.
            Duration duration = new Duration(TimeSpan.FromSeconds(duracion));

            // Create two DoubleAnimations and set their properties.
            DoubleAnimation myDoubleAnimationTL = new DoubleAnimation();
            DoubleAnimation myDoubleAnimationTR = new DoubleAnimation();
            DoubleAnimation myDoubleAnimationBR = new DoubleAnimation();
            DoubleAnimation myDoubleAnimationBL = new DoubleAnimation();

            myDoubleAnimationTL.Duration = duration;
            myDoubleAnimationTR.Duration = duration;
            myDoubleAnimationBR.Duration = duration;
            myDoubleAnimationBL.Duration = duration;

            Storyboard sb = new Storyboard();
            sb.Duration = duration;

            //double VertTo = offset;// -70;




            //NOTE : There are two methods because the different geometries, LineSegment and PathFigure...
            PointAnimation pa1TL, pa1TR, pa1BR, pa1BL, pa2TL, pa2TR, pa3TL, pa3TR;
            if (collapsed == true)
            {
                //Rectangulo superior
                 pa1TL = GenPointStartAnimation(option, "Front", ocMenuItems[option].TL);
                 pa1TR = GenPointAnimation(option, 1, "Front", ocMenuItems[option].TR);
                 pa1BR = GenPointAnimation(option, 2, "Front", ocMenuItems[option].BR);
                 pa1BL = GenPointAnimation(option, 3, "Front", ocMenuItems[option].BL);
                //Rectangulo derecho
                 pa2TL = GenPointStartAnimation(option, "Right", ocMenuItems[option].TR);
                 pa2TR = GenPointAnimation(option, 3, "Right", ocMenuItems[option].BR);
                //Rectangulo inferior
                 pa3TL = GenPointStartAnimation(option, "Bottom", ocMenuItems[option].BL);
                 pa3TR = GenPointAnimation(option, 1, "Bottom", ocMenuItems[option].BR);
            }
            else {
                //Rectangulo superior
                pa1TL = GenPointStartAnimation(option, "Front", ocMenuItems[option].E_TL);
                pa1TR = GenPointAnimation(option, 1, "Front", ocMenuItems[option].E_TR);
                pa1BR = GenPointAnimation(option, 2, "Front", ocMenuItems[option].E_BR);
                pa1BL = GenPointAnimation(option, 3, "Front", ocMenuItems[option].E_BL);
                //Rectangulo derecho
                pa2TL = GenPointStartAnimation(option, "Right", ocMenuItems[option].E_TR);
                pa2TR = GenPointAnimation(option, 3, "Right", ocMenuItems[option].E_BR);
                //Rectangulo inferior
                pa3TL = GenPointStartAnimation(option, "Bottom", ocMenuItems[option].E_BL);
                pa3TR = GenPointAnimation(option, 1, "Bottom", ocMenuItems[option].E_BR);
            }

            //Front Plate
            DoubleAnimation daFP = new DoubleAnimation();
            String Name = "opt" + option.ToString() + "FrontPlate" + option.ToString();
            UserControl ucTarget = (UserControl)this.menuCanvas.FindName(Name);
            PropertyPath pp = new PropertyPath("(Canvas.Top)");
            Storyboard.SetTargetProperty(daFP, pp);
            Storyboard.SetTarget(daFP, ucTarget);

            if (collapsed == true)
            {
                daFP.To = ocMenuItems[option].TL.Y; //(double)ucTarget.GetValue(Canvas.TopProperty) + VertTo;
            }
            else
            {
                daFP.To = ocMenuItems[option].E_TL.Y;
            }

            //If this option is the selected one, we should animate:
            //1. the color band to the right
            //2. the apparition of the information panel.
            //DoubleAnimation daColorBand = new DoubleAnimation();;
            //DoubleAnimation daInfoPanel;
            //if (selected == true) {
            //    Rectangle r = (Rectangle)ucTarget.FindName("ColorBlock");
            //    PropertyPath ppR = new PropertyPath("(Width)");
            //    Storyboard.SetTargetProperty(daColorBand, ppR);
            //    Storyboard.SetTarget(daColorBand, r);

            //    if (collapsed == false)
            //        daColorBand.To = (double)Block_Width;
            //    else
            //        daColorBand.To = (double)50;
            //}

            //Generamos una lista para tratar las animaciones de punto de forma automatica
            List<PointAnimation> lpa = new List<PointAnimation>();
            lpa.Add(pa1TL);
            lpa.Add(pa1TR);
            lpa.Add(pa1BR);
            lpa.Add(pa1BL);
            lpa.Add(pa2TL);
            lpa.Add(pa2TR);
            lpa.Add(pa3TL);
            lpa.Add(pa3TR);
            
            //El easing que aplicaremos a todas las animaciones
            var easing = new BounceEase();
            easing.Bounces = 2;
            easing.EasingMode = EasingMode.EaseIn;
            var ElasticEase = new ElasticEase();
            ElasticEase.EasingMode = EasingMode.EaseOut;
            ElasticEase.Oscillations = 1;
            ElasticEase.Springiness = 1;

            var ease4 = new SineEase();
            ease4.EasingMode = EasingMode.EaseIn;

            IEasingFunction ief;
            //Asignamos la función de ease
            //if (offset < 0)
            if (collapsed == false)
            {
                ief = ElasticEase; // easing;
            }
            else
            {
                ief = ease4;
            }

            //Aplicamos el easing y añadimos todas las animaciones al Storyboard
            foreach (var item in lpa)
            {
                item.EasingFunction = ief;
                //Añadimos las animaciones...
                sb.Children.Add(item);
            }

            //DoubleAnimation
            daFP.EasingFunction = ief;
            sb.Children.Add(daFP);
            //if (selected == true)
            //{
            //    daColorBand.EasingFunction = ief;
            //    sb.Children.Add(daColorBand);
            //}

            LayoutRoot.Resources.Add("animationofmenu" + option.ToString(), sb);
            sb.Begin();
            
            sb.Completed += new EventHandler(sb_Completed);
        }
        void sb_Completed(object sender, EventArgs e)
        {
            animating = false;
        }
        //private PointAnimation GenPointAnimation(int option, int LineSegmentPoint, string Type, double VerticalDestination) 
        private PointAnimation GenPointAnimation(int option, int LineSegmentPoint, string Type, Point DestinationPoint) 
        {
            String Name = "opt" + 
                          option.ToString() +
                          Type +
                          LineSegmentPoint.ToString();

            PointAnimation PAnim = new PointAnimation();
            //String Name = "opt" + "0" + "Front" + "1";
            LineSegment lsTarget = (LineSegment)this.menuCanvas.FindName(Name);
            PropertyPath pp = new PropertyPath("(Point)");
            Storyboard.SetTargetProperty(PAnim, pp);
            Storyboard.SetTarget(PAnim, lsTarget);
            PAnim.To = DestinationPoint; //new Point(lsTarget.Point.X, lsTarget.Point.Y + VerticalDestination);

            return PAnim;
        }
        //private PointAnimation GenPointStartAnimation(int option, string Type, double VerticalDestination)
        private PointAnimation GenPointStartAnimation(int option, string Type, Point DestinationPoint)
        {
            String Name = "opt" +
                          option.ToString() +
                          Type +
                          "0";

            PointAnimation PAnim = new PointAnimation();
            PathFigure pfTarget = (PathFigure)this.menuCanvas.FindName(Name);
            
            PropertyPath pp = new PropertyPath("(StartPoint)");
            Storyboard.SetTargetProperty(PAnim, pp);
            Storyboard.SetTarget(PAnim, pfTarget);
            //PAnim.To = new Point(pfTarget.StartPoint.X, pfTarget.StartPoint.Y + VerticalDestination);
            PAnim.To = DestinationPoint; //new Point(lsTarget.Point.X, lsTarget.Point.Y + VerticalDestination);

            return PAnim;
        }

        #region Deprecated Code
        private void DrawMenuItems(int Option, double offset)
        {
            //int i = 0;
            //this.menuCanvas.Children.Clear();
            //foreach (var m in ocMenuItems)
            //{
            //    MenuItem tmpMI = (MenuItem)m;
            //    if (i == Option) { 
            //        //Adjust the offset for the Front vertical axis
            //        tmpMI = new MenuItem()
            //        {
            //            BL = new Point(m.BL.X, m.BL.Y - offset),
            //            BR = new Point(m.BR.X, m.BR.Y - offset),
            //            TL = new Point(m.TL.X, m.TL.Y - offset),
            //            TR = new Point(m.TR.X, m.TR.Y - offset),
            //            BBL = m.BBL,
            //            BBR = m.BBR,
            //            BTL = m.BTL,
            //            BTR = m.BTR
            //        };
            //    }

            //    String BasePrefix = "opt" + Option.ToString();

            //    String prefix = BasePrefix + "Front";
            //    Path p = CreatePath(tmpMI.TL, tmpMI.TR, tmpMI.BR, tmpMI.BL, new SolidColorBrush(Colors.Blue), prefix);
            //    this.menuCanvas.Children.Add(p);

            //    prefix = BasePrefix + "Back";
            //    Path pR = CreatePath(tmpMI.BTL, tmpMI.BTR, tmpMI.BBR, tmpMI.BBL, new SolidColorBrush(Colors.Green), prefix);
            //    this.menuCanvas.Children.Add(pR);

            //    prefix = BasePrefix + "Right";
            //    Path rpR = CreatePath(tmpMI.TR, tmpMI.BTR, tmpMI.BBR, tmpMI.BR, new SolidColorBrush(Colors.Red), prefix);
            //    this.menuCanvas.Children.Add(rpR);

            //    prefix = BasePrefix + "Bottom";
            //    Path bpb = CreatePath(tmpMI.BL, tmpMI.BR, tmpMI.BBR, tmpMI.BBL, new SolidColorBrush(Colors.Orange), prefix);
            //    this.menuCanvas.Children.Add(bpb);

            //    i++;
            //}
            //this.menuCanvas.UpdateLayout();
        }
        #endregion Deprecated Code

    }
}
